home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Portable Patmos 1.1 / patmos-src / src / mmu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-01-19  |  16.9 KB  |  757 lines  |  [TEXT/KAHL]

  1. #ifdef THINK_C
  2. #include <LoMem.h>
  3. #include <THINK.h>
  4. #define get_time() TimeLM
  5. #define get_ticks() Ticks
  6. #else
  7. #include <Types.h>
  8. #include <Errors.h>
  9. #include <Memory.h>
  10. #include <OSUtils.h>
  11. #include <SegLoad.h>
  12. #include <Quickdraw.h>
  13. #include <Files.h>
  14. #include <Menus.h>
  15. #include <Fonts.h>
  16. #include <Resources.h>
  17. #include <GestaltEqu.h>
  18. #include <Traps.h>
  19. #include <Aliases.h>
  20. #include <Packages.h>
  21. #include <Processes.h>
  22. #include <AppleEvents.h>
  23. #include <ToolUtils.h>
  24. #include <SysEqu.h>
  25. #define get_time() (*(long *)TimeLM)
  26. #define get_ticks() (*(long *)Ticks)
  27. enum {FALSE,TRUE};
  28. #endif
  29. #include <GestaltEqu.h>
  30. #include <ToolUtils.h>
  31. #include <Retrace.h>
  32. #include <OSUtils.h>
  33. #include <stdio.h>
  34. #include <errno.h>
  35. #include <string.h>
  36. #include <stdlib.h>
  37. #include <dirent.h>
  38. #include <fcntl.h>
  39. #include <utime.h>            
  40. #include <unistd.h>
  41. #include <sys/uio.h>
  42. #include <sys/mman.h>
  43. #include <sys/stat.h>
  44. #include <sys/syscall.h>
  45. #include <sys/ioctl.h>
  46. #include <sys/syslimits.h>
  47. #include <sys/time.h>
  48. #include <sys/resource.h>
  49. #include <sys/signal.h>
  50. #include <sys/signalvar.h>
  51. #include <sys/ptrace.h>
  52. #include <sys/wait.h>
  53. #include "crtlocal.h"
  54. #include "proc_mmu.h"
  55.  
  56. struct page_chain *head = 0;
  57. struct mmu *crp,*swapper;
  58.  
  59. #define unixTime(t) (t - (time_t)0x7c25b080)
  60.  
  61. int kernel_errno;
  62. unsigned char interrupt;
  63. long kInterval=12;    /* set for 1/5 second between calls */
  64.  
  65. long *system_vectors = 0;
  66.  
  67. long activated_pages = 0;
  68. long page_size,old_ticks;
  69. long user_vectors[256];
  70. long supervisor_vectors[256];
  71.  
  72. #if 0
  73. CursHandle nxt[8];
  74. unsigned char ccnt;
  75. #endif
  76.  
  77. #ifdef PROTECTED
  78.  
  79. int check2(struct mmu *crp, unsigned long addr)
  80.     {
  81.     Zone    *pzone = ApplicZone();
  82.     long    phys_addr = (long)LTP(addr);
  83.     if (mmutype == -1) return 0;
  84.     if (phys_addr==-1)
  85.         {
  86.         crp->result = -1;
  87.         errno = EFAULT;
  88.         return -1;
  89.         }
  90.     if (0 && debug && (addr >= crp->sbreak) 
  91.               && ((addr < crp->registers.save[15]) || (addr >= crp->stack_limit)))
  92.                       {
  93.                     char err[99];
  94.                     ksprintf(err+1, "Possible bus error soon, logical address %8.8X\n", addr);
  95.                     *err = strlen(err+1);
  96.                       DebugStr((ConstStr255Param)err);
  97.                       }
  98.     if ((phys_addr < (long)&(pzone->heapData)) || (phys_addr >= (long)(pzone->bkLim)))
  99.         {
  100.         char err[99];
  101.         ksprintf(err+1, "Physical address %8.8X outside kernel memory\n", phys_addr);
  102.         *err = strlen(err+1);
  103.         DebugStr((ConstStr255Param)err);
  104.         }
  105.     return 0;
  106.     }
  107.  
  108. #define CHECK(addr) CHECK2(crp, addr)
  109.  
  110. void setmaxstack(long value)
  111.     {
  112.     crp->maxstack = value;
  113.     if (value > stack_headroom*2) value = stack_headroom*2;
  114.     upper_space(crp, value);
  115.     }
  116.  
  117. #endif
  118.  
  119. void patch_traps(void)
  120.     {
  121.     int i = 16;
  122.     long old_sr;
  123. #ifdef PROTECTED
  124.     if (virtual) old_sr = EnterSupervisorMode();
  125. #endif
  126.     system_vectors = (long *)vbr();
  127. #ifdef PROTECTED
  128.     if (virtual) asm
  129.         {
  130.         move.w    old_sr,sr
  131.         }
  132. #endif
  133.     memcpy(supervisor_vectors, system_vectors, sizeof(supervisor_vectors));
  134.     memcpy(user_vectors, system_vectors, sizeof(user_vectors));
  135.     while (--i) user_vectors[i+32] = (long)trap_patch_1();
  136.     user_vectors[32] = (long)trap_patch_0();
  137. #ifdef PROTECTED
  138.     if (virtual)
  139.         ((long *)0)[2] = (long)trap_patch_1();    /* bus error */
  140.     else
  141. #endif
  142.         user_vectors[2] = (long)trap_patch_1();    /* bus error */
  143.     user_vectors[3] = (long)trap_patch_1();    /* address error */
  144.     user_vectors[4] = (long)trap_patch_1();    /* illegal inst */
  145.     user_vectors[5] = (long)trap_patch_1();    /* zero divide */
  146.     user_vectors[6] = (long)trap_patch_1();    /* range error */
  147.     user_vectors[7] = (long)trap_patch_1();    /* trapv */
  148.     user_vectors[8] = (long)trap_patch_1();    /* privilege */
  149.     user_vectors[9] = (long)trap_patch_1();    /* trace */
  150. //    user_vectors[10] = (long)trap_patch_1();    /* line-A emulation */
  151.     user_vectors[11] = (long)trap_patch_1();    /* Line-F emulation */
  152.     }
  153.  
  154. static recursive = 0;
  155.  
  156. void *xmalloc(size_t siz)
  157.     {
  158.     void *ptr = malloc(siz);
  159.     if (!ptr)
  160.         {
  161.         kInterval = 0;
  162.         if (recursive) 
  163.             {
  164.             ExitToShell();
  165.             }
  166.         recursive = 1;
  167.         kprintf("Out of memory\n");
  168.         while (!Button());
  169.         exit(1);
  170.         }
  171.     memset(ptr, 0, siz);
  172.     return ptr;
  173.     }
  174.  
  175. void *xrealloc(void *oldptr, size_t siz)
  176.     {
  177.     void *ptr = realloc(oldptr, siz);
  178.     if (!ptr)
  179.         {
  180.         kInterval = 0;
  181.         if (recursive) 
  182.             {
  183.             ExitToShell();
  184.             }
  185.         recursive = 1;
  186.         kprintf("Out of memory\n");
  187.         while (!Button());
  188.         exit(1);
  189.         }
  190.     return ptr;
  191.     }
  192.  
  193. #ifdef PROTECTED
  194. int ukmemcpy(struct mmu *crp, long dest, void *src, long siz)
  195.     {
  196.     if (siz > 0)
  197.         {
  198.         CHECK(dest);
  199.         CHECK(dest+siz-1);
  200.         if (virtual)
  201.             {
  202.             memcpy((void *)dest, src, siz);
  203.             return 0;
  204.             }
  205.         put_user_root((long)crp);
  206.         flush_mmu_caches();
  207.         put_dfc(2);
  208.         asm    {
  209.             move.l    siz,d1
  210.             move.l    src,a1
  211.             move.l    dest,a0
  212.         @1:    move.b    (a1)+,d0
  213.             moves.b    d0,(a0)+
  214.             subq.l    #1,d1
  215.             bne        @1
  216.             }
  217.         }
  218.     return 0;
  219.     }
  220.     
  221. long ustrlen(struct mmu *crp, long src)
  222.     {
  223.     long result;
  224.     CHECK(src);
  225.     if (virtual) return strlen((void *)src);
  226.     put_user_root((long)crp);
  227.     flush_mmu_caches();
  228.     put_sfc(2);
  229.     asm    {
  230.         move.l    src,a1
  231.     @1:    moves.b    (a1)+,d0
  232.         tst.b    d0
  233.         bne        @1
  234.         move.l    a1,result
  235.         }
  236.     return result-src-1;
  237.     }
  238.  
  239. int kustrcpy(struct mmu *crp, void *dest, long src)
  240.     {
  241.     CHECK(src);
  242.     if (virtual) 
  243.         {
  244.         strcpy((void *)dest, (void *)src);
  245.         return 0;
  246.         }
  247.     put_user_root((long)crp);
  248.     flush_mmu_caches();
  249.     put_sfc(2);
  250.     asm    {
  251.         move.l    src,a1
  252.         move.l    dest,a0
  253.     @1:    moves.b    (a1)+,d0
  254.         move.b    d0,(a0)+
  255.         bne        @1
  256.         }
  257.     return 0;
  258.     }
  259.  
  260. int kumemcpy(struct mmu *crp, void *dest, long src, long siz)
  261.     {
  262.     if (siz > 0)
  263.         {
  264.         CHECK(src);
  265.         CHECK(src+siz-1);
  266.         if (virtual)
  267.             {
  268.             memcpy(dest, (void *)src, siz);
  269.             return 0;
  270.             }
  271.         put_user_root((long)crp);
  272.         flush_mmu_caches();
  273.         put_sfc(2);
  274.         asm    {
  275.             move.l    siz,d1
  276.             move.l    src,a1
  277.             move.l    dest,a0
  278.         @1:    moves.b    (a1)+,d0
  279.             move.b    d0,(a0)+
  280.             subq.l    #1,d1
  281.             bne        @1
  282.             }
  283.         }
  284.     return 0;
  285.     }
  286.  
  287. int umemset(struct mmu *crp, long dest, char value, long siz)
  288.     {
  289.     if (siz > 0)
  290.         {
  291.         CHECK(dest);
  292.         CHECK(dest+siz-1);
  293.         if (virtual)
  294.             {
  295.             memset((void *)dest, value, siz);
  296.             return 0;
  297.             }
  298.         put_user_root((long)crp);
  299.         flush_mmu_caches();
  300.         put_dfc(2);
  301.         asm    {
  302.             move.l    siz,d1
  303.             move.b    value,d0
  304.             move.l    dest,a0
  305.         @1:    moves.b    d0,(a0)+
  306.             subq.l    #1,d1
  307.             bne        @1
  308.             }
  309.         }
  310.     return 0;
  311.     }
  312.  
  313. int uumemcpy(struct mmu *destrp, struct mmu *srcrp, long dest, long src, long size)
  314.     {
  315.     enum     {bufsiz=8192};
  316.     char    *kbuf = xmalloc(bufsiz);
  317.     long    uaddr = 0;
  318.     CHECK2(srcrp, src);
  319.     CHECK2(destrp, dest);
  320.     CHECK2(srcrp, src+size-1);
  321.     CHECK2(destrp, dest+size-1);
  322.     while (size > 0)
  323.         {
  324.         long amount = size>bufsiz?bufsiz:size;
  325.         kumemcpy(srcrp, kbuf, src, amount);
  326.         src += amount;
  327.         ukmemcpy(destrp, dest, kbuf, amount);
  328.         dest += amount;
  329.         size -= amount;
  330.         }
  331.     free(kbuf);
  332.     return 0;
  333.     }
  334.  
  335. int uread(struct mmu *crp, int fd, long useraddr, long size)
  336.     {
  337.     enum    {bufsiz=8192};
  338.     char    *kbuf = xmalloc(bufsiz);
  339.     while (size > 0)
  340.         {
  341.         long amount = size>bufsiz?bufsiz:size;
  342.         long actual = read(fd, kbuf, amount);
  343.         if (actual > 0)
  344.             {
  345.             ukmemcpy(crp, useraddr, kbuf, actual);
  346.             useraddr += actual;
  347.             size -= actual;
  348.             }
  349.         else 
  350.             {
  351.             if (!actual) kprintf("Caution - executable too short for header\n");
  352.             size = 0;
  353.             }
  354.         }
  355.     free(kbuf);
  356.     return 0;
  357.     }
  358.  
  359. int page_free(long addr)
  360.     {
  361.     struct page_chain *ptr = head;
  362.     long buf,tries;
  363.     if (addr) while (ptr)
  364.         {
  365.         if (((ptr->free_list[0]&~0x80000000L) <= addr) && 
  366.             ((ptr->free_list[sizeof(head->pages)/page_size-1]&~0x80000000L) >= addr))
  367.             {
  368.             buf = (addr - (ptr->free_list[0]&~0x80000000L))/page_size;
  369.             if (ptr->free_list[buf] == ((addr&~(page_size-1))|0x80000000L))
  370.                 {
  371.                 ptr->free_list[buf] &= ~0x80000000L;
  372.                 if (ptr->idx == -1) ptr->idx = buf;
  373.                 return --activated_pages;
  374.                 }
  375.             }
  376.         ptr = ptr->nxt;
  377.         }
  378.     return activated_pages;
  379.     }
  380.  
  381. long page_alloc(void)
  382.     {
  383.     struct page_chain *ptr = head;
  384.     long buf,tries;
  385.     while (ptr)
  386.         {
  387.         tries = 256;
  388.         if (ptr->idx != -1)
  389.             {
  390.             do
  391.                 ptr->idx = (ptr->idx+1)&255;
  392.             while ((ptr->free_list[ptr->idx] <= 0) && --tries);
  393.             if (tries)
  394.                 {
  395.                 buf = ptr->free_list[ptr->idx];
  396.                 ptr->free_list[ptr->idx] ^= 0x80000000L;
  397.                 ++activated_pages;
  398.                 memset((void *)buf, 0, page_size);
  399.                 return buf;
  400.                 }
  401.             else ptr->idx = -1;    /* all pages used */
  402.             }
  403.         ptr = ptr->nxt;
  404.         }
  405.     ptr = malloc(sizeof(struct page_chain));
  406.     if (ptr)
  407.         {
  408.         ptr->nxt = head;
  409.         head = ptr;
  410.         buf = ((((long)head->padding)|(page_size-1))+1);
  411.         tries = sizeof(head->pages)/page_size;
  412.         while (tries--)
  413.             {
  414.             long addr = buf+tries*page_size;
  415.             head->free_list[tries] = (addr);
  416.             }
  417.         head->free_list[head->idx] ^= 0x80000000L;
  418.         ++activated_pages;
  419.         memset((void *)buf, 0, page_size);
  420.         return buf;
  421.         }
  422.     errno = ENOMEM;
  423.     return 0;
  424.     }
  425.  
  426. #endif
  427.  
  428. void read_memory(long addr, void *buf, long maxlen)
  429.     {
  430.     kumemcpy(crp, buf, addr, maxlen);
  431.     }
  432.  
  433. short nxt_pid = 1;
  434.  
  435. int newproc(char *kbuf, char **args, char **envs, struct mmu *parent, long argcnt, long envcnt)
  436.     {
  437.     long addr2,addr;
  438.     long siz = 0;
  439.     int proc_no = 0;
  440.     char *buf = (void *)xmalloc(512+sizeof(struct mmu));
  441.     crp = (struct mmu *)((((long)buf)|511)+1);
  442.     crp->self = buf;
  443.     crp->stack_limit = 1<<25;
  444.     crp->parent = parent;
  445.     crp->root_parID = root_parID;
  446.     crp->crt_parID = crt_parID;
  447.     crp->pid = nxt_pid++;
  448.     crp->state = 'R';
  449.     crp->p_sigacts = (struct sigacts *)xmalloc(sizeof(struct sigacts));
  450.     while (proc_tab[proc_no] && (proc_no < sizeof(proc_tab)/sizeof(*proc_tab)))
  451.         ++proc_no;
  452.     if (proc_tab[proc_no])
  453.         {
  454.         kInterval = 0;
  455.         exit(1);
  456.         }
  457.     proc_tab[proc_no] = crp;
  458. #ifdef PROTECTED
  459.     wipeout(crp);
  460. #endif
  461.     if (kbuf)
  462.         {
  463.         int proc = open(kbuf, O_RDONLY);
  464.         if (proc < 0)
  465.             {
  466.             crp->state = 'Z';
  467.             return proc;
  468.             }
  469.         if (parent)
  470.             {
  471.             memcpy(crp->fd_tab, parent->fd_tab, sizeof(crp->fd_tab));
  472.             crp->trace_me = parent->trace_me;
  473.             }
  474.         else
  475.             {
  476. #if 1
  477.             static winidx = 0;
  478.             int console = next_fd(1);
  479.             crt_fd_tab[console].fd = (100<<8)|++winidx;    /* console */
  480.             crt_fd_tab[console].flags = O_RDWR|O_PIPE;
  481. #else
  482.             int console = open("/dev/console", O_RDWR);
  483.             if (console == -1)
  484.                 {
  485.                 kprintf("Creating /dev/console ...");
  486.                 mkdir("/dev", 0777);
  487.                 mknod("/dev/console", S_IFCHR|0666, 100<<8);
  488.                 console = open("/dev/console", O_RDWR);
  489.                 if (console == -1)
  490.                     {
  491.                     kprintf(" failed - sorry !\n");
  492.                     exit(99);
  493.                     }
  494.                 else
  495.                     {
  496.                     kprintf(" succeeded\n");
  497.                     }
  498.                 }
  499. #endif
  500.             crp->fd_tab[0] = crp->fd_tab[1] = crp->fd_tab[2] = console;
  501.             }
  502.         read(proc, (void *)&(crp->header), sizeof(crp->header));
  503.         if (N_BADMAG(crp->header))
  504.             {
  505.             char **args;
  506.             long *addr = (long *)(crp->registers.save[15]);
  507.             char *default_shell = "/bin/sh";
  508.             char *shell = (char *)&(crp->header);
  509.             if (*shell++ != '#') shell = default_shell;
  510.             else if (*shell++ == '!')
  511.                 {
  512.                 char *end = strchr(shell,'\n');
  513.                 if (end) *end = 0;
  514.                 else shell = default_shell;
  515.                 }
  516.             else shell = default_shell;
  517.             close(proc);
  518.             proc = open(shell, O_RDONLY);            
  519.             read(proc, (void *)&(crp->header), sizeof(crp->header));
  520.             if (N_BADMAG(crp->header))
  521.                 {
  522.                 errno = ENOEXEC;
  523.                 crp->state = 'Z';
  524.                 return -1;
  525.                 }
  526.             kumemcpy(crp, args, (long)addr, sizeof(long));
  527.             ukmemcpy(crp, (long)--addr, args, sizeof(long));
  528.             crp->registers.save[15] = (long)addr;
  529.             crp->registers.save[14]++;
  530.             
  531.             }
  532.         if (crp->header.a_trsize || crp->header.a_drsize)
  533.             {
  534.             extern void *big_stack;
  535.             long stack_headroom = 1<<16;
  536.             long resource_size = loader_main(proc, &(crp->header));
  537.             if (resource_size == -1)
  538.                 {
  539.                 crp->state = 'Z';
  540.                 return -1;
  541.                 }
  542. #ifdef PROTECTED
  543.               supervisor_space(crp, crp->header.a_entry, crp->header.a_entry+resource_size);
  544.             kprintf("Relocatable module, entry point %X\n", crp->header.a_entry);
  545. #endif
  546.             crp->storage = (struct mem_chain *)(crp->header.a_entry-sizeof(struct exec));
  547.             SetPtrSize((void *)crp->storage,
  548.                 N_DATOFF(crp->header) + 
  549.                 (crp->header).a_data + 
  550.                 (crp->header).a_bss);
  551.  
  552.             if (big_stack)
  553.                 {
  554.                 stack_headroom = stack_headroom*4 + resource_size/4;
  555. #ifdef DEBUGSTACK
  556.                 kprintf("Stack boosted to %d bytes for %s\n", stack_headroom, kbuf);
  557. #endif
  558.                 }
  559.             crp->storage->nxt = (struct mem_chain *)NewPtrClear(stack_headroom);
  560.             if (MemError())
  561.                 {
  562.                 crp->state = 'Z';
  563.                 return -1;
  564.                 }
  565.             crp->stack_limit = ((long)crp->storage->nxt) + stack_headroom;
  566. #ifdef PROTECTED
  567.               supervisor_space(crp, ((long)crp->storage->nxt), crp->stack_limit);
  568. #endif
  569.             crp->registers.save[15] = crp->stack_limit-256;
  570.             }
  571.         else
  572.             {
  573. #ifdef PROTECTED
  574.             if (virtual)
  575. #endif
  576.                 {
  577.                 kprintf("Sorry, this machine cannot run protected mode executables\n");
  578.                 crp->state = 'Z';
  579.                 return -1;
  580.                 }
  581. #ifdef PROTECTED
  582.             if (upper_space(crp, stack_headroom))
  583.                 {
  584.                 crp->state = 'Z';
  585.                 return -1;
  586.                 }
  587.             crp->registers.save[15] = crp->stack_limit-256;
  588.             crp->sbreak = N_ALIGN(crp->header, N_BSSADDR(crp->header) + crp->header.a_bss);
  589.             if (lower_space(crp, crp->sbreak))
  590.                 {
  591.                 crp->state = 'Z';
  592.                 return -1;
  593.                 }
  594.             lseek(proc, N_TXTOFF(crp->header), 0);
  595.             uread(crp,proc, N_TXTADDR(crp->header), crp->header.a_text);
  596.             lseek(proc, N_DATOFF(crp->header), 0);
  597.             uread(crp,proc,N_DATADDR(crp->header), crp->header.a_data);
  598.             umemset(crp,N_BSSADDR(crp->header), 0, crp->header.a_bss);
  599. #endif
  600.             }
  601.         close(proc);
  602.         if (parent) parent->state = 'Z';
  603.         crp->registers.pc = crp->header.a_entry;
  604.         }
  605.     else /* !kbuf */
  606.         {
  607.         int usp = parent->registers.save[15];
  608.         crp->sbreak = parent->sbreak;
  609.         crp->registers = parent->registers;
  610. #ifdef PROTECTED
  611.         if (lower_space(crp, crp->sbreak))
  612.             {
  613.             crp->state = 'Z';
  614.             return -1;
  615.             }
  616.         uumemcpy(crp, parent, 0, 0, crp->sbreak);    /* duplicate prog+data space */
  617.         if (upper_space(crp, crp->stack_limit-usp+stack_headroom))
  618.             {
  619.             crp->state = 'Z';
  620.             return -1;
  621.             }
  622.         uumemcpy(crp, parent, usp, usp, crp->stack_limit-usp);    /* duplicate stack space */
  623. #else
  624.         crp->stack_limit = parent->stack_limit;
  625.         if (parent->savestack)
  626.             parent->savestack = xrealloc(parent->savestack, crp->stack_limit-usp);
  627.         else
  628.             parent->savestack = xmalloc(crp->stack_limit-usp);
  629.         kumemcpy(parent, parent->savestack, usp, crp->stack_limit-usp);
  630.         crp->savestack = xmalloc(crp->stack_limit-usp);
  631.         kumemcpy(parent, crp->savestack, usp, crp->stack_limit-usp);
  632. #endif
  633.         memcpy(crp->fd_tab, parent->fd_tab, sizeof(crp->fd_tab));
  634.         crp->header = parent->header;
  635.         crp->root_parID = parent->root_parID;
  636.         crp->crt_parID = parent->crt_parID;
  637.         crp->trace_me = parent->trace_me;
  638.         *(crp->p_sigacts) = *(parent->p_sigacts);
  639.         }
  640.     if (argcnt)
  641.         {
  642.         long *addr = (long *)(crp->stack_limit-256);
  643.         long i;
  644.         for (i = envcnt; i--; )
  645.             {
  646.             int len = strlen(envs[i]);
  647.             addr -= len+4 >> 2;
  648.             ukmemcpy(crp, (long)addr, envs[i], len+1);
  649.             free(envs[i]);
  650.             envs[i] = (char *)addr;
  651.             }
  652.         for (i = argcnt; i--; )
  653.             {
  654.             int len = strlen(args[i]);
  655.             addr -= len+4 >> 2;
  656.             ukmemcpy(crp, (long)addr, args[i], len+1);
  657.             free(args[i]);
  658.             args[i] = (char *)addr;
  659.             }
  660.         if (envcnt)
  661.             {
  662.             umemset(crp, (long)--addr, 0, sizeof(long));
  663.             for (i = envcnt; i--; )
  664.                 ukmemcpy(crp, (long)--addr, &envs[i], sizeof(long));
  665.             ukmemcpy(crp, (long)(addr-1), &addr, sizeof(long));
  666.             addr--;
  667.             }
  668.         umemset(crp, (long)--addr, 0, sizeof(long));
  669.         for (i = argcnt; i--; )
  670.             ukmemcpy(crp, (long)--addr, &args[i], sizeof(long));
  671.         ukmemcpy(crp, (long)--addr, args, sizeof(long));
  672.         crp->registers.save[15] = (long)addr;
  673.         crp->registers.save[14] = argcnt;
  674.         }
  675.     return 0;
  676.     }
  677.  
  678. /* Prototypes */
  679. OSErr InstallVBL (void);
  680. pascal long GetVBLRec (void);
  681. void DoVBL (unsigned short fault);
  682.  
  683. void ProcessDoc (FSSpec *curDocFSS)
  684.     {
  685.     extern char **environ;
  686.     char cname[64];
  687.     char *args[2] = {cname, 0};
  688.     short refnum;
  689.     crt_ioVRefNum = curDocFSS->vRefNum;
  690.     root_parID = crt_parID = curDocFSS->parID;
  691.     memcpy(cname, &(curDocFSS->name[1]), curDocFSS->name[0]);
  692.     cname[curDocFSS->name[0]] = 0;
  693.     newproc(cname, args, environ, 0, 1, 1);
  694.     }
  695.  
  696. #ifdef PROTECTED
  697.  
  698. typedef struct VBLRec {
  699.     VBLTask    myVBLTask;
  700.     long    vblA5;    /* 4 bytes before the VBLTask data */
  701. } VBLRec, *VBLRecPtr;
  702.  
  703. /* Globals */
  704. VBLRec gMyVBLRec;    /* global VBL record */
  705.  
  706. pascal long GetVBLRec (void)
  707.     = 0x2E88;
  708.  
  709. OSErr InstallVBL ()
  710. {
  711.     long addr,addr2;
  712.     long page = page_alloc();
  713.     char *buf = (void *)xmalloc(512+sizeof(struct mmu));
  714.     swapper = (struct mmu *)((((long)buf)|511)+1);
  715.     swapper->self = buf;
  716.     memset((void *)page, 0x4E, page_size);
  717.     for (addr = 0; addr < 128; addr++)
  718.         {
  719.         swapper->u.u4.level1[addr] = 0xA + (long)(swapper->u.u4.level2);
  720.         swapper->u.u4.level2[addr] = 0xA + (long)&(swapper->u.u4.level3[addr][0]);
  721.         for (addr2 = (1<<18)/page_size; addr2--; )
  722.             {
  723.             swapper->u.u4.level3[addr][addr2] = 0x39 + page;
  724.             }
  725.         }
  726.     gMyVBLRec.myVBLTask.qType = vType;
  727.     gMyVBLRec.myVBLTask.vblAddr = (ProcPtr) DoVBL;/* address of task */
  728.     gMyVBLRec.myVBLTask.vblCount = kInterval; /* Set the interval */
  729.     gMyVBLRec.vblA5 = (long) CurrentA5; /* Save app's A5 in structure */
  730.  
  731.     return VInstall((QElemPtr) &gMyVBLRec.myVBLTask);
  732. }
  733.  
  734. /* ============= the VBL task code itself  =============*/
  735.  
  736. void DoVBL(unsigned short fault)
  737.     {
  738.     long    curA5;
  739.     VBLRecPtr    recPtr;
  740.  
  741.     recPtr = (VBLRecPtr) GetVBLRec ();
  742.     curA5 = SetA5 (recPtr->vblA5);
  743.                                     /* read app A5 from structure and save */
  744.                                         /* current value of A5 */
  745.  
  746.     /* ...  now that it's OK to access application variables, do the task ... */
  747.  
  748.     flush_mmu_caches();
  749.     if (system_vectors[46] == (long)trap_patch_1()) put_user_root((long)swapper);
  750.     flush_mmu_caches();
  751.  
  752.     /* Reset vblCount so that this procedure executes again */
  753.     recPtr->myVBLTask.vblCount = kInterval;
  754.     curA5 = SetA5(curA5);
  755.     }
  756.  
  757. #endif